/**
 * 项目名：	Rumba Plan
 * 
 * 版权所有(C)，上海海鼎信息工程股份有限公司，2007，所有权利保留。
 * 
 * 文件名：	BRoleShareAgent.java
 * 模块说明：	
 * 修改历史：
 * Nov 2, 2007 - guzhidi - 创建。
 */
package com.hd123.rumba.user.biz.share;

import java.util.ArrayList;
import java.util.Collection;
import java.util.List;

import net.sf.hibernate.Hibernate;
import net.sf.hibernate.HibernateException;
import net.sf.hibernate.Session;
import net.sf.hibernate.Transaction;
import net.sf.hibernate.type.Type;

import com.hd123.rumba.domain.IDomain;
import com.hd123.rumba.domain.IDomainMgr;
import com.hd123.rumba.exception.BusinessException;
import com.hd123.rumba.organization.IOrganization;
import com.hd123.rumba.organization.IOrganizationMgr;
import com.hd123.rumba.organization.biz.IBOrganizationMgr;
import com.hd123.rumba.organization.biz.SOrganization;
import com.hd123.rumba.runtime.IVersionedPersistent;
import com.hd123.rumba.runtime.NamingMgr;
import com.hd123.rumba.runtime.OperateContext;
import com.hd123.rumba.user.CRole;
import com.hd123.rumba.user.IRole;
import com.hd123.rumba.user.IRoleDomain;
import com.hd123.rumba.user.IRoleMgr;
import com.hd123.rumba.util.ClassifiedHashtable;
import com.hd123.rumba.util.CollectionMatcher;

/**
 * @author guzhidi
 * 
 */
public class BRoleShareAgent implements IBRoleShareAgent {

  /** role的uuid */
  protected String roleUuid = null;

  public BRoleShareAssign getShareAssign(String domainUuid) throws BusinessException,
      HibernateException {
    checkIn();
    BRoleShareAssign sa = new BRoleShareAssign();
    IBOrganizationMgr orgMgr = (IBOrganizationMgr) NamingMgr.getInstance().lookupMgr(
        IBOrganizationMgr.class);
    SOrganization org = (SOrganization) orgMgr.getOrganizationByOrgDomain(domainUuid,
        SOrganization.class);
    sa.setOrganization(org);
    sa.setDomainUuid(domainUuid);
    sa.setChecked(this.getChecked(domainUuid));
    sa.setChildrenCount(this.getChildrenCount(domainUuid));
    return sa;
  }

  protected void checkIn() throws BusinessException, HibernateException {
    if (roleUuid == null)
      throw new BusinessException("指定属性roleUuid不可为空。");
  }

  protected Session getSession() throws BusinessException, HibernateException {
    return getDomainMgr().getSession();
  }

  private IDomainMgr domainMgr = null;

  private IDomainMgr getDomainMgr() throws BusinessException {
    if (domainMgr == null)
      domainMgr = (IDomainMgr) NamingMgr.getInstance().lookupMgr(IDomainMgr.class);
    return domainMgr;
  }

  private IRoleMgr roleMgr = null;

  private IRoleMgr getRoleMgr() throws BusinessException {
    if (roleMgr == null)
      roleMgr = (IRoleMgr) NamingMgr.getInstance().lookupMgr(IRoleMgr.class);
    return roleMgr;
  }

  public List<BRoleShareAssign> getLowerShareAssigns(String domainUuid) throws BusinessException,
      HibernateException {
    checkIn();
    List<BRoleShareAssign> brsas = new ArrayList<BRoleShareAssign>();
    IOrganizationMgr orgMgr = (IOrganizationMgr) NamingMgr.getInstance().lookupMgr(
        IOrganizationMgr.class);
    IOrganization org = orgMgr.getOrganizationByOrgDomain(domainUuid);
    List subOrgs = orgMgr.getLowerOrganizations(org);
    for (int i = 0; i < subOrgs.size(); i++) {
      IOrganization subOrg = (IOrganization) subOrgs.get(i);
      brsas.add(getShareAssign(subOrg.getOrganizationDomain().getUuid()));
    }
    return brsas;
  }

  private Integer getChildrenCount(String domainUuid) throws HibernateException, BusinessException {
    IOrganizationMgr orgMgr = (IOrganizationMgr) NamingMgr.getInstance().lookupMgr(
        IOrganizationMgr.class);
    IOrganization org = orgMgr.getOrganizationByOrgDomain(domainUuid);
    List subOrgs = orgMgr.getLowerOrganizations(org);
    return Integer.valueOf(subOrgs.size());
  }

  private boolean getChecked(String domainUuid) throws HibernateException, BusinessException {
    List list = getSession().find(
        "select o from " + IRoleDomain.class.getName()
            + " o where o.role.uuid = ? and o.domain.uuid = ?", new Object[] {
            roleUuid, domainUuid }, new Type[] {
            Hibernate.STRING, Hibernate.STRING });
    return list.size() > 0;
  }

  public void setRoleUuid(String roleUuid) throws BusinessException {
    this.roleUuid = roleUuid;
  }

  public String getRoleUuid() throws BusinessException {
    return this.roleUuid;
  }

  @SuppressWarnings("unchecked")
  public void executeCommandsT(List<BRoleShareCommand> cmds, OperateContext operate, long oca)
      throws HibernateException, BusinessException {
    checkIn();
    IRole prole = getRoleMgr().getRole(roleUuid);
    ClassifiedHashtable h = checkOca(prole, oca, CRole.CAPTION_CLASS, prole.getNameCode());
    if (h != null)
      throw new BusinessException(h.getAllMessages());

    List<String> oldDomains = (List<String>) getSession().find(
        "select o.domain.uuid from " + IRoleDomain.class.getName() + " o "
            + " where o.role.uuid = ?", roleUuid, Hibernate.STRING);

    // 进行命令的操作
    List<String> newDomains = new ArrayList<String>();
    newDomains.addAll(oldDomains);
    for (int i = 0; i < cmds.size(); i++) {
      BRoleShareCommand cmd = cmds.get(i);
      if (BRoleShareCommand.VALUE_COMMAND_CHECK.equals(cmd.getCommand())) {
        if (!newDomains.contains(cmd.getDomainUuid()))
          newDomains.add(cmd.getDomainUuid());
      } else if (BRoleShareCommand.VALUE_COMMAND_UNCHECK.equals(cmd.getCommand())) {
        if (newDomains.contains(cmd.getDomainUuid()))
          newDomains.remove(cmd.getDomainUuid());
      } else if (BRoleShareCommand.VALUE_COMMAND_CHECKALL.equals(cmd.getCommand())) {
        List<IOrganization> subOrgs = getSubOrgs(cmd.getDomainUuid());
        for (int k = 0; k < subOrgs.size(); k++)
          if (!newDomains.contains(subOrgs.get(k).getOrganizationDomain().getUuid()))
            newDomains.add(subOrgs.get(k).getOrganizationDomain().getUuid());
      } else if (BRoleShareCommand.VALUE_COMMAND_UNCHECKALL.equals(cmd.getCommand())) {
        List<IOrganization> subOrgs = getSubOrgs(cmd.getDomainUuid());
        for (int k = 0; k < subOrgs.size(); k++)
          if (newDomains.contains(subOrgs.get(k).getOrganizationDomain().getUuid()))
            newDomains.remove(subOrgs.get(k).getOrganizationDomain().getUuid());
      }
    }
    // 禁止删除当前域
    if (!newDomains.contains(prole.getDomain().getUuid()))
      newDomains.add(prole.getDomain().getUuid());

    Transaction tx = getSession().beginTransaction();
    try {
      CollectionMatcher<String, String> cm = new CollectionMatcher<String, String>();
      // 删除
      Collection<String> deleted = cm.subtractA(oldDomains, newDomains);
      for (String domainUuid : deleted) {
        IDomain domain = getDomainMgr().getDomain(domainUuid);
        getRoleMgr().unshareRoleFromDomain(prole, domain, operate);
      }
      // 增加
      Collection<String> added = cm.subtractA(newDomains, oldDomains);
      for (String domainUuid : added) {
        IDomain domain = getDomainMgr().getDomain(domainUuid);
        getRoleMgr().shareRoleToDomain(prole, domain, operate);
      }
      tx.commit();
    } catch (Exception e) {
      tx.rollback();
      throw new BusinessException(e);
    }
  }

  @SuppressWarnings("unchecked")
  public List<IOrganization> getSubOrgs(String domainUuid) throws BusinessException,
      HibernateException {
    IOrganizationMgr orgMgr = (IOrganizationMgr) NamingMgr.getInstance().lookupMgr(
        IOrganizationMgr.class);
    IOrganization parentOrg = orgMgr.getOrganizationByOrgDomain(domainUuid);
    List<IOrganization> subOrgs = orgMgr.getAllLowerOrganizations(parentOrg);
    return subOrgs;
  }

  protected ClassifiedHashtable checkOca(IVersionedPersistent entity, long oca,
      String classCaption, String entitySpec) throws BusinessException {
    if (entity.getUuid() != null && entity.getOca() != oca) {
      ClassifiedHashtable h = new ClassifiedHashtable();
      h.putMessage("oca", ClassifiedHashtable.ERROR, "指定" + classCaption + "[" + entitySpec
          + "]已经被其他用户修改，操作将被取消。");
      return h;
    } else
      return null;
  }
}
